﻿using System.Collections.Generic;
using UnityEngine;
namespace UIDCToolsProfiler
{
    public class UIDCTools
    {
        public static Texture[] styles = null;
        private static List<UIDCDrawRectInfo> list = new List<UIDCDrawRectInfo>();
        private static Dictionary<int, bool> maskDic = new Dictionary<int, bool>();
        private static Texture emptyTexture = null;
        public static int DefaultDepth = 1000;

        public static Texture GetEmptyTexture()
        {
            if(emptyTexture == null)
            {
                emptyTexture = GenTextureColor(50, 30, new Color(0,0,0,0));
            }
            return emptyTexture;
        }
        public static void ClearTexture()
        {
            if(styles == null)
            {
                return;
            }
            int count = styles.Length;
            for(int i = count - 1; i >= 0;i--)
            {
                Texture tex = styles[i];
                Object.DestroyImmediate(tex);
            }
            styles = null;
        }
        public static void InitStyles(int batchCount)
        {
            styles = new Texture[batchCount];
            for (int i = 0; i < styles.Length; ++i)
            {
                float value = (float)i / batchCount;
                int maxColorValue = 255 * 3;
                float colorValue = maxColorValue * value;
                Color color = Color.black;
                if (colorValue > 255 *2)
                {
                    color = new Color((colorValue - 255 * 2)/ 255, 1,1,1);
                }else if(colorValue > 255)
                {
                    color = new Color(0, (colorValue - 255) / 255, 1, 1);
                }else
                {
                    color = new Color(0, 0, colorValue / 255, 1);
                }
                styles[i] = GenTextureColor(70, 16, color);
            }
        }
        private static Texture2D GenTextureColor(int width, int height, Color color)
        {
            Texture2D t = new Texture2D(width, height);
            for (int i = 0, imax = t.width; i < imax; i++)
            {
                for (int j = 0, jmax = t.height; j < jmax; j++)
                {
                    t.SetPixel(i, j, color);
                }
            }
            t.Apply();

            return t;
        }
        public static Texture GetStyles(int id, int batchCount)
        {
            if (styles == null)
            {
                InitStyles(batchCount);
            }
            return styles[id];
        }

        public static void GenTreeInfo(UIDCTreeNode node)
        {
            if (node.IsRoot)
            {
                Dictionary<int, KeyValuePair<UIDCTreeNode, List<UIDCDrawRectInfo>>> rectInfos = new Dictionary<int, KeyValuePair<UIDCTreeNode, List<UIDCDrawRectInfo>>>();
                rectInfos.Add(1, new KeyValuePair<UIDCTreeNode, List<UIDCDrawRectInfo>>(node, new List<UIDCDrawRectInfo>()));
                List<KeyValuePair<UIDCTreeNode, UINodeInfo>> infos = node.GetNodesInfo();
                int idx = 0;
                for (int i = 0; i < infos.Count; ++i)
                {
                    if (infos[i].Value.Use)
                    {
                        UIDCDrawRectInfo rectInfo = new UIDCDrawRectInfo(infos[i].Value.Name, infos[i].Value.IsOnlyCanvas);
                        rectInfo.Depth = infos[i].Value.Depth;
                        rectInfo.HierarychyOrder = idx++;
                        rectInfo.MaterialInstanceID = infos[i].Value.MaterialInstanceID;
                        rectInfo.TextureID = infos[i].Value.TextureID;
                        rectInfo.Corners = infos[i].Value.Corners;
                        rectInfo.IsInMask = infos[i].Value.IsInMask;
                        rectInfo.IsInMask2D = infos[i].Value.IsInMask2D;
                        infos[i].Value.ConnectInfo(rectInfo);
                        if (!rectInfos.ContainsKey(rectInfo.Depth / DefaultDepth))
                        {
                            rectInfos[rectInfo.Depth / DefaultDepth] = new KeyValuePair<UIDCTreeNode, List<UIDCDrawRectInfo>>(infos[i].Key, new List<UIDCDrawRectInfo>());
                        }
                        rectInfos[rectInfo.Depth / DefaultDepth].Value.Add(rectInfo);
                    }
                }

                if (rectInfos.Count > 0)
                {
                    int allBatchCount = 0;
                    int allMaskBatchCount = 0;
                    KeyValuePair<int, int> temp;
                    foreach (var keyValue in rectInfos)
                    {
                        temp = CalculateDepthInCanvas(keyValue.Value.Key, keyValue.Value.Value);
                        allBatchCount += temp.Key;
                        allMaskBatchCount += temp.Value;
                    }
                    node.batchCount = allBatchCount;
                    node.maskBatchCount = allMaskBatchCount;
                }
            }
        }

        private static KeyValuePair<int, int> CalculateDepthInCanvas(UIDCTreeNode node, List<UIDCDrawRectInfo> rectInfos)
        {
            if (rectInfos.Count == 0)
            {
                return new KeyValuePair<int, int>(0, 0);
            }
            list.Clear();
            list.Add(rectInfos[0]);

            for (int i = 1; i < rectInfos.Count; ++i)
            {
                CalculateDepth(rectInfos[i]);
                list.Add(rectInfos[i]);
            }
            rectInfos.Sort();

            rectInfos[0].BatchID = rectInfos[0].Depth;
            for (int i = 1; i < rectInfos.Count; ++i)
            {
                if ((rectInfos[i].Depth == rectInfos[i - 1].Depth && rectInfos[i].CanBatch(rectInfos[i - 1])) || rectInfos[i].IsOnlyCanvas)
                {
                    rectInfos[i].BatchID = rectInfos[i - 1].BatchID;
                }
                else
                {
                    rectInfos[i].BatchID = rectInfos[i - 1].BatchID + 1;
                }
                //rectInfos[i].Print();
            }

            for (int i = 0; i < rectInfos.Count - 2; ++i)
            {
                for (int j = i + 1; j < rectInfos.Count; ++j)
                {
                    if (rectInfos[i].BatchID != rectInfos[j].BatchID && rectInfos[i].CanBatch(rectInfos[j]))
                    {
                        rectInfos[i].check = rectInfos[j].HierarychyOrder;
                        rectInfos[j].check = rectInfos[i].HierarychyOrder;
                    }
                }
            }

            maskDic.Clear();
            for (int i = 0; i < rectInfos.Count; ++i)
            {
                if (rectInfos[i].IsInMask == 0 && !maskDic.ContainsKey(rectInfos[i].BatchID))
                {
                    maskDic.Add(rectInfos[i].BatchID, true);
                }
            }

            node.maskBatchCount = maskDic.Count;
            node.batchCount = rectInfos[rectInfos.Count - 1].BatchID - rectInfos[0].Depth + 1 + maskDic.Count;
            node.UpdataInfo();
            UIDCDrawRectLine ui = node.AssetObject.GetComponent<UIDCDrawRectLine>();
            if (ui == null)
            {
                ui = node.AssetObject.AddComponent<UIDCDrawRectLine>();
            }
            ui.SetDrawRectInfoList(rectInfos);
            return new KeyValuePair<int, int>(node.batchCount, node.maskBatchCount);
        }

        private static void CalculateDepth(UIDCDrawRectInfo a)
        {
            a.Depth = list[0].Depth;
            for (int i = 0; i < list.Count; ++i)
            {
                if (Intersects(a.GetRect(), list[i].GetRect()))
                {
                    int depth = list[i].Depth + 1;
                    if (list[i].CanBatch(a))
                    {
                        depth = list[i].Depth;
                    }
                    a.Depth = depth > a.Depth ? depth : a.Depth;
                }
            }
        }

        private static bool Intersects(Rect a, Rect b)
        {
            if (a.xMax > b.xMin && b.xMax > a.xMin && a.yMax > b.yMin && b.yMax > a.yMin)
            {
                return true;
            }

            return false;
        }
    }
}
